use crate::config::config::MyConfig;
use include_dir::{include_dir, Dir};
use serde_json::json;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

static TEMPLATE_DIR: Dir<'_> = include_dir!("src/template");
pub fn init(args: &MyConfig) -> anyhow::Result<()> {
    //判断name在本地是否有同名文件夹或文件
    if let Ok(_) = fs::metadata(&args.name) {
        return Err(anyhow::anyhow!("name已经存在: {}", &args.name));
    }
    //输出文件
    if let Err(e) = init_template(&TEMPLATE_DIR, &args) {
        return Err(anyhow::anyhow!("模板文件解析失败: {e}"));
    }
    Ok(())
}
pub fn init_template(dir: &Dir, args: &MyConfig) -> anyhow::Result<()> {
    let project_name = args.name.clone();
    for entry in dir.entries() {
        if let Some(x) = entry.as_dir() {
            init_template(x, args)?;
        } else {
            let file_path = entry.path();
            let mut output_path_buf = PathBuf::new();
            output_path_buf.push(project_name.clone());
            output_path_buf.push(file_path);
            let output_path = output_path_buf.to_str().unwrap();
            let parent_dir = std::path::Path::new(output_path).parent().unwrap();
            if !args.test {
                fs::create_dir_all(parent_dir)?;
            }
            if let Some(content) = entry.as_file().unwrap().contents_utf8() {
                //替换文字
                let new_content = resolve_template(content, &args);
                if new_content.is_err() {
                    let error = new_content.err().unwrap();
                    let err_msg = error.to_string();
                    let msg = format!("模板解析失败, path:{output_path}, msg:{err_msg}");
                    return Err(anyhow::anyhow!("{}", msg));
                }
                let new_content = new_content?;
                if !args.test {
                    let mut file = File::create(output_path)?;
                    file.write_all(new_content.as_bytes())?;
                }
            } else {
                if !args.test {
                    let mut file = File::create(output_path)?;
                    file.write_all(entry.as_file().unwrap().contents())?;
                }
            }
        }
    }
    Ok(())
}
fn resolve_template(content: &str, template: &MyConfig) -> anyhow::Result<String> {
    // 由于模板中有大量的大括号，所以要修改语法标签，否则就要全部转义，太麻烦了
    let syntax = upon::Syntax::builder()
        .expr("<%", "%>")
        .block("<[", "]>")
        .build();

    let mut engine = upon::Engine::with_syntax(syntax);
    engine.add_template("source", content)?;
    // engine.add_filter("date_filter", upon_date_filter);
    // engine.add_filter("message_filter", upon_message_filter);
    let template_value = json!(template); // 将template转换为serde_json::Value
    let result = engine
        .template("source")
        .render(upon::value! {template: &template_value})
        .to_string()?;
    Ok(result)
}
